package org.bysun.ggcip;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.bysun.ggcip.http.IpDto;
import org.bysun.ggcip.http.MyTrustStrategy;
import org.bysun.ggcip.http.MyX509HostnameVerifier;
import org.bysun.ggcip.http.Validator;
import org.bysun.ggcip.parse.IpAddrParse;

import javax.net.ssl.HttpsURLConnection;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * User: bysun
 * Date: 2014/6/7 0007
 * Time: 15:52
 */
public class Main {
    public static void main(String[] args){
        try {
            init();
        } catch (Exception e) {
            System.out.println("链接参数初始化失败,程序终止!");
            System.exit(1);
        }


        final int poolSize = Commons.PPS.getInteger("ggcip.valid.poolsize",10), // 验证ip的线程数
            timeout = Commons.PPS.getInteger("ggcip.conn.timeoout",500), // 链接超时时间
            maxSize = Commons.PPS.getInteger("ggcip.max.size",50); // 最大获取有效ip的个数


        Scanner scanner = new Scanner(System.in);
        Set<String> ipSet = getIpSet(scanner);
        ExecutorService pool = Executors.newFixedThreadPool(poolSize);
        final List<IpDto> dtos = new CopyOnWriteArrayList<>();
        for (String s : ipSet) {
            final IpDto dto = new IpDto(s);
            pool.execute(new Runnable() {
                private Validator validator = new Validator(timeout);
                @Override
                public void run() {
                    if(dtos.size()>=maxSize)
                        return;

                    validator.valid(dto);
                    if(dto.isUseful()){
                        System.out.println("获取到有效IP:"+dto.getIp()+",响应时间为:"+dto.getConnTime()+"毫秒");
                        dtos.add(dto);
                    }
                }
            });
        }

        pool.shutdown();
        try {
            while (!pool.isTerminated()) {
                Thread.sleep(2000);
            }
        } catch (InterruptedException e) {
            System.out.println("系统错误.");
        }
        IpDto[] dtoArr = dtos.toArray(new IpDto[dtos.size()]);
        Arrays.sort(dtoArr);

        // 写出csv文件和txt文件
        FileWriter csv = null , txt = null;

        try {
            String base = Main.class.getClassLoader().getResource("").getFile();
            long time = System.currentTimeMillis();
            csv = new FileWriter(base+"result-"+time+".csv");
            txt = new FileWriter(base+"result-"+time+".txt");

            for (IpDto dto : dtoArr) {
                csv.write(dto.getIp()+","+dto.getConnTime()+"\n\r");
                txt.write(dto.getIp()+"|");
            }
        } catch (IOException e) {
            System.out.println("文件被锁定或者有同名文件夹,无法将结果保存为文件");
        } finally {
            IOUtils.closeQuietly(csv);
            IOUtils.closeQuietly(txt);
        }


    }

    private static Set<String> getIpSet(Scanner scanner) {
        Map<String, Set<String>> ips = IpAddrParse.parse();
        List<String> areaNames = new ArrayList<>(ips.keySet());

        String areaKey = null;
        while (StringUtils.isBlank(areaKey)){
            System.out.println("请输入数字选择需要验证ip的区域,推荐[tw,hk,jp,sp]");
            for (int i = 0; i < areaNames.size(); i++) {
                String name = areaNames.get(i);
                System.out.print(i+"-"+name+"; ");
                if(i%4==3)
                    System.out.println();
            }
            System.out.println();
            int num = scanner.nextInt();
            areaKey = areaNames.get(num);
            if(StringUtils.isBlank(areaKey)){
                System.out.println("选择错误请重新选择");
            }
        }
        return ips.get(areaKey);
    }

    private static void init() throws Exception {
        SSLContextBuilder sslBuilder = SSLContexts.custom();
        sslBuilder.loadTrustMaterial(null, new MyTrustStrategy());
        HttpsURLConnection.setDefaultSSLSocketFactory(sslBuilder.build().getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new MyX509HostnameVerifier());
    }
}
